// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
// "Software"), to deal in the Software without restriction, including
// without limitation the rights to use, copy, modify, merge, publish,
// distribute, sublicense, and/or sell copies of the Software, and to
// permit persons to whom the Software is furnished to do so, subject to
// the following conditions:
// 
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
// 
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
// MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
// LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
// OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
// WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
// Copyright (c) 2004 Scott Willeke (http://scott.willeke.com)
//
// Authors:
//	Scott Willeke (scott@willeke.com)
//
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Windows.Forms;
using LessMsi.Msi;
using LessMsi.UI.Model;
using Misc.Windows.Forms;
using System.Diagnostics;

namespace LessMsi.UI
{
    partial class MainForm : Form, IMainFormView
    {
        public MainForm(string defaultInputFile)
        {
            InitializeComponent();

            fileGrid.AutoGenerateColumns = false;

            Presenter = new MainFormPresenter(this);
            Presenter.Initialize();

            SelectedMsiFilePath = defaultInputFile;
            Presenter.LoadCurrentFile();
        }

        private MainFormPresenter Presenter { get; set; }

        #region IMainFormView Implementation

        static void AutoSizeColumns(DataGridView grid)
        {
            foreach (DataGridViewColumn col in grid.Columns)
                col.Width = col.GetPreferredWidth(DataGridViewAutoSizeColumnMode.AllCells, true);
        }

        public void AutoSizeGridColumns()
        {
            AutoSizeColumns(fileGrid);
            AutoSizeColumns(msiTableGrid);
            AutoSizeColumns(msiPropertyGrid);
        }

        public string SelectedMsiFilePath
        {
            get { return txtMsiFileName.Text; }
            set { txtMsiFileName.Text = value; }
        }

        public string SelectedTableName
        {
            get { return cboTable.Text; }
        }

        public void ChangeUiEnabled(bool doEnable)
        {
            btnExtract.Enabled = doEnable;
            cboTable.Enabled = doEnable;
        }

        public MsiPropertyInfo SelectedMsiProperty
        {
            get
            {
                if (msiPropertyGrid.SelectedRows.Count > 0)
                    return msiPropertyGrid.SelectedRows[0].DataBoundItem as MsiPropertyInfo;
                else
                    return null;
            }
        }

        public string PropertySummaryDescription
        {
            get { return txtSummaryDescription.Text; }
            set { txtSummaryDescription.Text = value; }
        }

        public void ShowUserMessageBox(string message)
        {
            MessageBox.Show(this, message, "LessMSI", MessageBoxButtons.OK, MessageBoxIcon.Information);
        }

        #region MSI Table Grid Stuff

        #region Property Grid Stuff
        public void SetPropertyGridDataSource(MsiPropertyInfo[] props)
        {
            msiPropertyGrid.DataSource = props;
        }

        public void AddPropertyGridColumn(string boundPropertyName, string headerText)
        {
            DataGridViewColumn col = new DataGridViewTextBoxColumn { DataPropertyName = boundPropertyName, HeaderText = headerText };
            msiPropertyGrid.Columns.Add(col);
        }
        #endregion

        #endregion

        #endregion

        #region UI Event Handlers
        private void OpenFileCommand()
        {
            openMsiDialog.FileName = SelectedMsiFilePath;

            var result = openMsiDialog.ShowDialog(this);

            if (DialogResult.OK != result)
                return;

            SelectedMsiFilePath = openMsiDialog.FileName;
            Presenter.LoadCurrentFile();

            //to make sure shortcut keys for menuitems work properly select a grid:
            if (tabs.SelectedTab == tabExtractFiles)
                fileGrid.Select();
            else if (tabs.SelectedTab == tabTableView)
                msiTableGrid.Select();
            else if (tabs.SelectedTab == tabSummary)
                msiPropertyGrid.Select();
        }

        private void ReloadCurrentUIOnEnterKeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyValue == 13)
            {
                e.Handled = true;
                Presenter.LoadCurrentFile();
            }
        }

        private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            Presenter.UpdateMSiTableGrid();
        }

        private void btnExtract_Click(object sender, EventArgs e)
        {
            //TODO: Refactor to Presenter
            var selectedFiles = new List<MsiFile>();
            if (fileGrid.SelectedRows.Count == 0)
            {
                ShowUserMessageBox("Please select some or all of the files to extract them.");
                return;
            }

            FileInfo msiFile = Presenter.SelectedMsiFile;

            if (msiFile == null)
                return;

            if (folderBrowser.SelectedPath == null || folderBrowser.SelectedPath.Length <= 0)
                folderBrowser.SelectedPath = msiFile.DirectoryName;

            if (DialogResult.OK != folderBrowser.ShowDialog(this))
                return;

            btnExtract.Enabled = false;
            using (var progressDialog = BeginShowingProgressDialog())
            {
                try
                {
                    DirectoryInfo outputDir = new DirectoryInfo(folderBrowser.SelectedPath);
                    foreach (DataGridViewRow row in fileGrid.SelectedRows)
                    {
                        MsiFileItemView fileToExtract = (MsiFileItemView)row.DataBoundItem;
                        selectedFiles.Add(fileToExtract.File);
                    }


                    var filesToExtract = selectedFiles.ToArray();
                    Wixtracts.ExtractFiles(msiFile, outputDir, filesToExtract,
                                           new AsyncCallback(progressDialog.UpdateProgress));
                }
                catch (Exception err)
                {
                    MessageBox.Show(this,
                                    "The following error occured extracting the MSI: " + err.ToString(), "MSI Error!",
                                    MessageBoxButtons.OK, MessageBoxIcon.Error
                        );
                }
            }
            btnExtract.Enabled = true;
        }

        private ExtractionProgressDialog BeginShowingProgressDialog()
        {
            var progressDialog = new ExtractionProgressDialog(this);
            progressDialog.Show();
            progressDialog.Update();
            return progressDialog;
        }

        #endregion


        private void btnSelectAll_Click(object sender, EventArgs e)
        {
            Presenter.ToggleSelectAllFiles(true);
        }

        private void btnUnselectAll_Click(object sender, EventArgs e)
        {
            Presenter.ToggleSelectAllFiles(false);
        }

        private void msiPropertyGrid_SelectionChanged(object sender, EventArgs e)
        {
            Presenter.OnSelectedPropertyChanged();
        }

        private void preferencesToolStripMenuItem_Click(object sender, EventArgs e)
        {
            var frm = new PreferencesForm();
            frm.ShowDialog(this);
        }

        private void openToolStripMenuItem_Click(object sender, EventArgs e)
        {
            OpenFileCommand();
        }

        private void btnBrowse_Click(object sender, EventArgs e)
        {
            OpenFileCommand();
        }

        private void copyToolStripMenuItem_Click(object sender, EventArgs e)
        {
            // copying the currently selected row in the currently selected ListView here:
            var grid = ActiveControl as DataGridView;
            WinFormsHelper.CopySelectedDataGridRowsToClipboard(grid);
        }

        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
        {
            new AboutBox().ShowDialog(this);
        }
    }
}